if True:
import numpy as np
import pandas as pd
# Add lab library
import sys
sys.path.insert(0, '/home/trevormjs/Documents/Science/APL/Lab')
#---------------------------------------------------------------------#
# matplotlib plotting #
#---------------------------------------------------------------------#
import matplotlib.pyplot as plt
import matplotlib as mpl
from jupyterthemes import jtplot
from Helper.plotting import my_graph
# Edit the font, font size, and axes width
# mpl.rcParams['font.family'] = 'Avenir'
plt.rcParams['font.size'] = 24
plt.rcParams['axes.linewidth'] = 2
jtplot.style(theme='monokai', context='notebook', ticks=False, grid=False)
#---------------------------------------------------------------------#
# bokeh plotting #
#---------------------------------------------------------------------#
from bokeh.plotting import figure, show, output_notebook
from bokeh.themes import Theme
from bokeh.io import curdoc, export_png
from bokeh.models import (Range1d, Label, ColumnDataSource, LabelSet,
Legend)
from Helper.plotting import style
output_notebook()
# curdoc().theme = Theme(filename="../Helper/theme.yml")
#---------------------------------------------------------------------#
# error and unit handling #
#---------------------------------------------------------------------#
from uncertainties import ufloat
import Helper.numbers as nu
from Helper.record import Measurement, Unit
%load_ext autoreload
%autoreload 2
pd.set_option('plotting.backend', 'pandas_bokeh')
x = np.linspace(0, .1, 2048)
y = np.sin(2*np.pi*100*x)
window = np.hamming(len(x))
coefs = np.fft.fft(window*y)
freqs = np.fft.fftfreq(y.shape[0], d=x[1]-x[0])
1/(x[1]-x[0])
20470.0
fig = figure(width=600, height=400)
fig.line(x, y, line_width=3)#, color = 'blue')
# fig.line(x, np.hamming(y.shape[0]), color = 'red')
# fig.line(x, y*window, color = 'purple')
# fig.x_range = Range1d(80, 120)
style(fig, 'x (s)','y')
show(fig)
export_png(fig, filename = '../Images/l5_A_1a.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_A_1a.png'
fig = figure(width=600, height=400)
fig.line(np.fft.fftshift(freqs), np.fft.fftshift(np.abs(coefs)), line_width=3)
fig.x_range = Range1d(70, 130)
style(fig, 'Frequency (Hz)', 'Amplitude')
show(fig)
export_png(fig, filename = '../Images/l5_A_1b.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_A_1b.png'
nu.halfmax(np.abs(coefs), [coefs.argmax()])[0]*(freqs[1]-freqs[0])
array([17.42189888])
freqs[1]-freqs[0]
9.9951171875
freqs.max()
10225.0048828125
1/(x[1]-x[0])
2047.0
x = np.linspace(0, 1, 2048)
y = np.sin(2*np.pi*100*x)
window = np.hamming(len(x))
coefs_2 = np.fft.fft(window*y)
freqs_2 = np.fft.fftfreq(y.shape[0], d=x[1]-x[0])
fig = figure(width=600, height = 400)
fig.line(x, y, line_width=3)
# fig.line(x, np.hamming(y.shape[0]), color = 'red')
# fig.line(x, y*window, color = 'purple')
# fig.x_range = Range1d(80, 120)
style(fig, 'x (s)','y')
# fig.yaxis.major_label_orientation = 'horizontal'
show(fig)
nu.halfmax(np.abs(coefs_2), [coefs_2.argmax()])[0]*(freqs_2[1]-freqs_2[0])
array([1.75386876])
freqs_2[1]-freqs_2[0]
0.99951171875
freqs_2.max()
1022.50048828125
1/(x[1]-x[0])
2047.0
fig = figure(height=400, width=600)
fig.line(np.fft.fftshift(freqs),
np.fft.fftshift(
np.abs(coefs))/np.abs(coefs).max(),
line_width=3,
legend_label='0.1 Seconds')
fig.line(np.fft.fftshift(freqs_2),
np.fft.fftshift(
np.abs(coefs_2))/np.abs(coefs_2).max(),
line_width=3,
color='firebrick',
legend_label='1.0 Seconds')
fig.x_range = Range1d(70, 130)
style(fig, 'Frequency (Hz)', 'Amplitude')
show(fig)
export_png(fig, filename = '../Images/l5_A_3.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_A_3.png'
The more cycles of a signal, the higher the certainty of the frequency. This is why we observe a linewidth of 17 Hz for the 10-cycle signal, and a linewidth of 1.7 for the 100-cycle signal.
The nyquist frequency is defined by the sample rate, which is the same for both signals. However, the number of frequency bins is defined by the number of total samples. Therefore, the range of frequency of the two signals is the same, but the one with more samples is slightly closer to the nyquist frequency due to the higher resolution.
[[sine_wave, sine_wave_params]] = nu.read_scope_csv('./Data/l5_B_a.csv')
sine_wave
sine_fft, freqs = nu.fft(sine_wave.mV, sine_wave.ts, 15)
fig = figure(height=400, width=600, title='Sine Wave\n Frequency Response')
fig.title.text_font_size='100pt'
fig.line(freqs/1000, sine_fft, line_width=3)
fig.x_range = Range1d(0, 11)
style(fig, 'Frequency (kHz)', 'Amplitude')
fig.xaxis.axis_label_text_font_size = '70pt'
fig.yaxis.axis_label_text_font_size = '70pt'
show(fig)
export_png(fig, filename = './troll.png')
{'record_length': [2500.0, 'Points'],
'sample_interval': [2e-06, 's'],
'trigger_point': [1250.0002, 'Samples']}
'/home/trevormjs/Documents/Science/APL/Lab/Lab5/troll.png'
[[square_wave, square_wave_params]] = nu.read_scope_csv('./Data/l5_B_b.csv')
square_wave
square_fft, freqs = nu.fft(square_wave.mV, square_wave.ts, 15)
fig = figure(height=400, width=600)
fig.line(freqs/1000, square_fft, line_width=3)
fig.x_range = Range1d(0, 11)
style(fig, 'Frequency (kHz)', 'Amplitude')
show(fig)
export_png(fig, filename = '../Images/l5_B_2.png')
{'record_length': [2500.0, 'Points'],
'sample_interval': [2e-06, 's'],
'trigger_point': [1250.0002, 'Samples']}
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_B_2.png'
[[fork, fork_config]] = nu.read_scope_csv('./Data/l5_C.csv', skiprows=200)
{'record_length': [nan, nan],
'sample_interval': [nan, nan],
'trigger_point': [nan, nan]}
fork.describe()
| ts | mV | |
|---|---|---|
| count | 2048.000000 | 2048.000000 |
| mean | 4.894000 | 0.019385 |
| std | 2.365404 | 0.095235 |
| min | 0.800000 | -0.196000 |
| 25% | 2.847000 | -0.052000 |
| 50% | 4.894000 | 0.016000 |
| 75% | 6.941000 | 0.084000 |
| max | 8.988001 | 0.296000 |
3.8/np.pi/2
0.6047887837492023
from IPython.display import Audio
fig = figure(height=400, width=600)
fig.line(fork.ts, fork.mV, legend_label='Tuning Forks')
fig.line(fork.ts, .15+.15*np.cos(.6*2*np.pi*fork.ts-1.55),
color='firebrick', legend_label='Beat estimate, cos(.6*2pi*t)', line_width=3, alpha = .5)
style(fig, 'Time (s)', 'Amplitude (mV)')
fig.legend.location = 'bottom_right'
fig.y_range = Range1d(-.37, .3)
show(fig)
export_png(fig, filename='../Images/l5_C_a.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_C_a.png'
fork_fft, freqs = nu.fft(fork.mV, fork.ts, 15)
fig = figure()
fig.line(freqs, fork_fft)
fig.x_range = Range1d(0, freqs.max())
show(fig)
[{i:[6.538*i-5.935*i]} for i in range(145, 155)]
[{145: [87.43500000000006]},
{146: [88.03800000000001]},
{147: [88.64100000000008]},
{148: [89.24400000000003]},
{149: [89.8470000000001]},
{150: [90.45000000000016]},
{151: [91.05300000000011]},
{152: [91.65600000000018]},
{153: [92.25900000000013]},
{154: [92.8620000000002]}]
150*6.538
980.7
[[whistle, whistle_params]] = nu.read_scope_csv('./Data/l5_D.csv')
fig = figure()
fig.line(whistle.ts, whistle.mV)
show(fig)
whistle_fft, freqs = nu.fft(whistle.mV, whistle.ts, )
fig = figure(height=300, width=600)
fig.line(freqs, whistle_fft, line_width=3)
fig.x_range = Range1d(0, freqs.max())
fig.xaxis.axis_label = 'Frequency (Hz)'
style(fig, 'Frequency (Hz)', 'Amplitude')
show(fig)
export_png(fig, filename='../Images/l5_D_1.png')
fig.x_range = Range1d(2325, freqs.max())
show(fig)
export_png(fig, filename='../Images/l5_D_1_zoomed.png')
{'record_length': [2500.0, 'Points'],
'sample_interval': [0.00019999999495, 's'],
'trigger_point': [1250.0001, 'Samples']}
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_D_1_zoomed.png'
[[t_whistle, whistle_params]] = nu.read_scope_csv('./Data/l5_D_1.csv')
[[a_whistle, whistle_params]] = nu.read_scope_csv('./Data/l5_D_2.csv')
{'record_length': [2500.0, 'Points'],
'sample_interval': [0.00019999999495, 's'],
'trigger_point': [1250.0001, 'Samples']}
{'record_length': [2500.0, 'Points'],
'sample_interval': [0.00019999999495, 's'],
'trigger_point': [1250.0001, 'Samples']}
a_whistle_fft, freqs = nu.fft(a_whistle.mV, a_whistle.ts, 15)
t_whistle_fft, freqs = nu.fft(t_whistle.mV, t_whistle.ts, 15)
fig = figure(height=300, width=600)
fig.line(freqs, a_whistle_fft/a_whistle_fft.max(),
color='blue', legend_label='adrian')
fig.line(freqs, t_whistle_fft/t_whistle_fft.max(),
color='orange', legend_label='trevor')
fig.x_range = Range1d(0, freqs.max())
fig.xaxis.axis_label = 'Frequency (Hz)'
style(fig)
show(fig)
export_png(fig, filename='../Images/l5_D_2.png')
fig.x_range = Range1d(995, 1045)
show(fig)
export_png(fig, filename='../Images/l5_D_2_zoomed.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_D_2_zoomed.png'
[[two_whistle, two_whistle_config]] = nu.read_scope_csv('./Data/TwoWhistle.csv', skiprows=2)
two_whistle
{'record_length': [2500.0, 'Points'],
'sample_interval': [0.0002, 's'],
'trigger_point': [1150.00005, 'Samples']}
| ts | mV | |
|---|---|---|
| 0 | -0.2300 | -0.10 |
| 1 | -0.2298 | 0.22 |
| 2 | -0.2296 | 0.20 |
| 3 | -0.2294 | -0.08 |
| 4 | -0.2292 | -0.32 |
| ... | ... | ... |
| 2043 | 0.1786 | 0.10 |
| 2044 | 0.1788 | 0.26 |
| 2045 | 0.1790 | 0.02 |
| 2046 | 0.1792 | -0.24 |
| 2047 | 0.1794 | -0.14 |
2048 rows × 2 columns
fig = figure()
fig.line(two_whistle.ts, two_whistle.mV)
two_whistle_fft, freqs = nu.fft(two_whistle.mV, two_whistle.ts, magnitude=False)
two_whistle_fft *= freqs
deriv = np.fft.ifft(two_whistle_fft)
fig.line(two_whistle.ts, np.imag(deriv)/600, color = 'red', alpha = .5)
fig.line(two_whistle.ts, .3+.3*np.cos(274.5/np.pi*two_whistle.ts-.8))
show(fig)
two_whistle_fft, freqs = nu.fft(two_whistle.mV, two_whistle.ts, 15)
fig = figure(width=600, height=400)
fig.line(freqs, two_whistle_fft, line_width=1)
peak_freqs, peaks, indeces = nu.peak(two_whistle_fft,
n_peaks=20,
distance=100,
height=.1,
prominence=1,
threshold=None,
# prominence=None,
indeces=freqs)
disp = peak_freqs[peak_freqs>0]
disp.sort()
display(disp)
fig.x_range = Range1d(0, freqs.max())
fig.xaxis.axis_label = 'Frequency (Hz)'
# style(fig, 'Frequency (Hz)','Amplitude')
show(fig)
export_png(fig, filename='../Images/l5_D_3_simultaneous_whistling.png')
array([ 395.5078125 , 953.06396484, 995.63598633, 1011.35253906,
1050.26245117, 1066.74194336, 1086.27319336, 1348.87695312,
2302.39868164])
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_D_3_simultaneous_whistling.png'
for vowel in ['a', 'e', 'o', 'u']:
[[whistle, whistle_params]] = nu.read_scope_csv(f'./Data/l5_E_{vowel}.csv')
# fig = figure(title=vowel)
# fig.line(whistle.ts, whistle.mV)
# show(fig)
whistle_fft, freqs = nu.fft(whistle.mV, whistle.ts, 15)
peak_freqs, peaks, indeces = nu.peak(whistle_fft,
n_peaks=30,
distance=150,
threshold=None,
prominence=None,
indeces=freqs)
disp = peak_freqs[peak_freqs > 0]
disp.sort()
display(disp)
fig = figure(title=f"The Frequency Signature of '{vowel}'",
height=300, width=600)
fig.title.text_font_size='20pt'
fig.line(freqs, np.abs(whistle_fft), line_width=3)
# fig.scatter(peak_freqs, peaks, color = 'firebrick')
fig.x_range = Range1d(-50, freqs.max())
style(fig, 'Frequency (Hz)', 'Aamplitude')
show(fig)
export_png(fig, filename='../Images/l5_E_'+vowel+'.png')
{'record_length': [2500.0, 'Points'],
'sample_interval': [9.9999997474e-05, 's'],
'trigger_point': [1250.0001, 'Samples']}
array([ 157.16285558, 314.02054056, 392.75455364, 471.18339613,
549.61223862, 628.04108111, 706.46992361, 784.8987661 ,
863.63277918, 942.06162167, 1020.49046416, 1098.91930665,
1177.34814914, 1255.77699163, 1334.51100472])
{'record_length': [2500.0, 'Points'],
'sample_interval': [9.9999997474e-05, 's'],
'trigger_point': [1250.0001, 'Samples']}
array([ 119.62687259, 186.15406194, 278.92592232, 372.30812389,
465.38515486, 559.07252702, 651.5392168 , 744.92141837,
2047.99985197, 2142.60273591, 2235.67976688, 2327.23094489,
2423.0545112 , 2794.44712331, 2888.43966606])
{'record_length': [2500.0, 'Points'],
'sample_interval': [9.9999997474e-05, 's'],
'trigger_point': [1250.0001, 'Samples']}
array([ 99.79078403, 199.58156805, 299.37235208, 399.1631361 ,
498.64874953, 598.74470415, 698.53548818, 798.02110161,
897.81188564, 997.60266966, 1097.69862428, 1197.48940831,
1297.28019233, 1397.07097636])
{'record_length': [2500.0, 'Points'],
'sample_interval': [9.9999997474e-05, 's'],
'trigger_point': [1250.0001, 'Samples']}
array([ 119.62687259, 176.99894414, 265.49841621, 353.69271769,
442.19218976, 529.47097946, 618.27562213, 703.72338826,
792.52803093, 879.80682063, 968.3062927 , 1055.89025299,
1142.25353091, 1229.8374912 , 1407.14160594])
[[guitar, guitar_params]] = nu.read_scope_csv(f'./Data/l5_F_guitar.csv')
[[single_string, single_string_params]] = nu.read_scope_csv(f'./Data/l5_F_single-string.csv')
{'record_length': [2500.0, 'Points'],
'sample_interval': [9.9999997474e-05, 's'],
'trigger_point': [1250.0001, 'Samples']}
{'record_length': [2500.0, 'Points'],
'sample_interval': [9.9999997474e-05, 's'],
'trigger_point': [1250.0001, 'Samples']}
instruments = pd.DataFrame({
't': guitar.ts,
'guitar': guitar.mV,
'1string': single_string.mV
}).iloc[:2048]
fig = figure()
fig.line(guitar.ts, guitar.mV, legend_label = 'guitar', color = 'firebrick')
fig.line(guitar.ts, single_string.mV, legend_label = 'single_string')
# fig.line(guitar2.ts, guitar2.mV, legend_label = 'guitar2', color = 'green')
style(fig, 't (s)', 'mV')
show(fig)
import math
def frequency_to_note(frequency):
# define constants that control the algorithm
NOTES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#',
'A', 'A#', 'B'] # these are the 12 notes in each octave
OCTAVE_MULTIPLIER = 2 # going up an octave multiplies by 2
KNOWN_NOTE_NAME, KNOWN_NOTE_OCTAVE, KNOWN_NOTE_FREQUENCY = (
'A', 4, 440) # A4 = 440 Hz
# calculate the distance to the known note
# since notes are spread evenly, going up a note will multiply by a constant
# so we can use log to know how many times a frequency was multiplied to get from the known note to our note
# this will give a positive integer value for notes higher than the known note, and a negative value for notes lower than it (and zero for the same note)l
note_multiplier = OCTAVE_MULTIPLIER**(1/len(NOTES))
frequency_relative_to_known_note = frequency / KNOWN_NOTE_FREQUENCY
distance_from_known_note = math.log(
frequency_relative_to_known_note, note_multiplier)
# round to make up for floating point inaccuracies
distance_from_known_note = round(distance_from_known_note)
# using the distance in notes and the octave and name of the known note,
# we can calculate the octave and name of our note
# NOTE: the "absolute index" doesn't have any actual meaning, since it doesn't care what its zero point is. it is just useful for calculation
known_note_index_in_octave = NOTES.index(KNOWN_NOTE_NAME)
known_note_absolute_index = KNOWN_NOTE_OCTAVE * \
len(NOTES) + known_note_index_in_octave
note_absolute_index = known_note_absolute_index + distance_from_known_note
note_octave, note_index_in_octave = note_absolute_index // len(
NOTES), note_absolute_index % len(NOTES)
note_name = NOTES[note_index_in_octave]
return (note_name, note_octave)
def get_peaks_etc(fft, freqs, skipfirst=False):
peak_freqs, peaks, indeces = nu.peak(fft,
n_peaks=60,
distance=200,
height=2,
threshold=None,
prominence=None,
indeces=freqs)
peaks = np.array(peaks)
peak_frequencies = peak_freqs[peak_freqs > 0]
A = peaks[peak_freqs > 0]
if skipfirst:
min_freq_ind = peak_frequencies.argmin()
peak_frequencies = peak_frequencies.tolist()
A = A.tolist()
peak_frequencies.pop(min_freq_ind)
peak_frequencies = np.array(peak_frequencies)
A.pop(min_freq_ind)
A = np.array(A)
mV = A.copy()
A /= A.max()
A *= 100
note = [frequency_to_note(f) for f in peak_frequencies]
N = np.round(
peak_frequencies/peak_frequencies.min())
harmonics = pd.DataFrame({'frequency': peak_frequencies,
'A': A,
'note': note,
'N': N,
'mV': mV})
harmonics = harmonics.loc[
harmonics.frequency.sort_values().index]
return harmonics, (peak_freqs, peaks, indeces)
guitar_fft, freqs = nu.fft(guitar.mV, guitar.ts, 15)
# guitar_fft /= guitar_fft.max()
single_string_fft, freqs = nu.fft(single_string.mV, guitar.ts, 15)
# single_string_fft /= single_string_fft.max()
# guitar2_fft, freqs2 = nu.fft(guitar2.mV, guitar2.ts, 17)
fig = figure()
# guitar_fft = guitar_fft/guitar_fft.max()
fig.line(freqs,
guitar_fft,
legend_label='guitar',
color='firebrick')
# single_string_fft = single_string_fft/single_string_fft.max()
fig.line(freqs,
single_string_fft,
legend_label='single_string')
# guitar2_fft = guitar2_fft/guitar2_fft.max()
# fig.line(freqs2,
# guitar2_fft,
# legend_label='guitar2',
# color='green')
guitar_harmonics, [peak_freqs, peaks, indeces] = get_peaks_etc(
guitar_fft, freqs, False)
display('Guitar peak frequencies', guitar_harmonics)
singlestring_harmonics, [peak_freqs, peaks, indeces] = get_peaks_etc(
single_string_fft, freqs, False)
display('Single-String peak frequencies', singlestring_harmonics)
fig.scatter(singlestring_harmonics.frequency,
singlestring_harmonics.mV, color='skyblue', size = 17, alpha = .75)
fig.scatter(guitar_harmonics.frequency,
guitar_harmonics.mV, color='firebrick', size = 17, alpha = .75)
fig.x_range = Range1d(0, max(freqs)/2)
fig.y_range = Range1d(-1, 98)
style(fig)
show(fig)
export_png(fig, filename='../Images/l5_f_extra.png')
'Guitar peak frequencies'
| frequency | A | note | N | mV | |
|---|---|---|---|---|---|
| 4 | 142.209497 | 19.383175 | (C#, 3) | 1.0 | 18.440513 |
| 0 | 284.113822 | 100.000000 | (C#, 4) | 2.0 | 95.136698 |
| 1 | 425.712978 | 50.225799 | (G#, 4) | 3.0 | 47.783167 |
| 6 | 567.312133 | 14.280660 | (C#, 5) | 4.0 | 13.586149 |
| 5 | 709.826800 | 16.166036 | (F, 5) | 5.0 | 15.379833 |
| 3 | 852.951808 | 22.886293 | (G#, 5) | 6.0 | 21.773263 |
| 7 | 996.992328 | 7.189610 | (B, 5) | 7.0 | 6.839957 |
| 2 | 1140.727678 | 23.456165 | (C#, 6) | 8.0 | 22.315421 |
| 8 | 1285.378539 | 4.805469 | (E, 6) | 9.0 | 4.571764 |
| 9 | 2424.885535 | 2.237780 | (D#, 7) | 17.0 | 2.128950 |
'Single-String peak frequencies'
| frequency | A | note | N | mV | |
|---|---|---|---|---|---|
| 16 | 119.932043 | 6.371470 | (A#, 2) | 1.0 | 5.003408 |
| 4 | 277.705240 | 22.887233 | (C#, 4) | 2.0 | 17.972960 |
| 10 | 415.337178 | 12.551392 | (G#, 4) | 3.0 | 9.856398 |
| 8 | 553.579456 | 16.464573 | (C#, 5) | 5.0 | 12.929352 |
| 12 | 693.042417 | 10.486229 | (F, 5) | 6.0 | 8.234659 |
| 0 | 830.674355 | 100.000000 | (G#, 5) | 7.0 | 78.528321 |
| 6 | 969.221804 | 18.963050 | (B, 5) | 8.0 | 14.891365 |
| 3 | 1107.769254 | 28.495755 | (C#, 6) | 9.0 | 22.377238 |
| 13 | 1246.316703 | 9.161764 | (D#, 6) | 10.0 | 7.194580 |
| 5 | 1385.169323 | 22.583865 | (F, 6) | 12.0 | 17.734730 |
| 1 | 1523.716773 | 81.466033 | (G, 6) | 13.0 | 63.973908 |
| 11 | 1661.959051 | 12.131977 | (G#, 6) | 14.0 | 9.527038 |
| 9 | 1800.811671 | 16.103885 | (A, 6) | 15.0 | 12.646111 |
| 2 | 1938.748780 | 35.881801 | (B, 6) | 16.0 | 28.177376 |
| 7 | 2077.601400 | 18.392281 | (C, 7) | 17.0 | 14.443150 |
| 15 | 2215.538508 | 6.591576 | (C#, 7) | 18.0 | 5.176254 |
| 14 | 2493.243748 | 8.053837 | (D#, 7) | 21.0 | 6.324543 |
| 17 | 3047.433545 | 3.043708 | (G, 7) | 25.0 | 2.390173 |
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_f_extra.png'
from bokeh.models import LinearAxis, tickers
tickers.CategoricalTicker()
# [f'{note[0]} {note[1]}' for note in singlestring_harmonics.note])
singlestring_harmonics[['N','note']].T.to_dict()
{4: {'N': 1.0, 'note': ('C#', 4)},
10: {'N': 1.0, 'note': ('G#', 4)},
8: {'N': 2.0, 'note': ('C#', 5)},
12: {'N': 2.0, 'note': ('F', 5)},
0: {'N': 3.0, 'note': ('G#', 5)},
6: {'N': 3.0, 'note': ('B', 5)},
3: {'N': 4.0, 'note': ('C#', 6)},
13: {'N': 4.0, 'note': ('D#', 6)},
5: {'N': 5.0, 'note': ('F', 6)},
1: {'N': 5.0, 'note': ('G', 6)},
11: {'N': 6.0, 'note': ('G#', 6)},
9: {'N': 6.0, 'note': ('A', 6)},
2: {'N': 7.0, 'note': ('B', 6)},
7: {'N': 7.0, 'note': ('C', 7)},
15: {'N': 8.0, 'note': ('C#', 7)},
14: {'N': 9.0, 'note': ('D#', 7)},
16: {'N': 11.0, 'note': ('G', 7)}}
labels = {int(N): f'{note[0]} {note[1]}' for N, note in zip(
singlestring_harmonics.N, singlestring_harmonics.note)}
labels.update({int(N): f'{note[0]} {note[1]}' for N, note in zip(
guitar_harmonics.N, guitar_harmonics.note)})
fig = figure(width=800, height=500)
fig.scatter(singlestring_harmonics.N, (singlestring_harmonics.A),
legend_label='singlestring', size=10)
fig.scatter(guitar_harmonics.N, (guitar_harmonics.A),
legend_label='guitar', color='firebrick', size=10)
style(fig, 'N Harmonic', 'Scaled Amplitude')
ax2 = LinearAxis(axis_label='Note',)
ax2.ticker = list(labels.keys())
ax2.major_label_overrides = labels
ax2.major_label_orientation = np.pi/4
ax2.major_label_text_font_size = '14pt'
ax2.axis_label_text_font_size = '20pt'
# ax2.major_label_orientation = "vertical"
fig.add_layout(ax2, 'above')
fig.xgrid.visible = True
fig.xgrid.minor_grid_line_color = 'navy'
fig.xgrid.minor_grid_line_alpha = 0.6
fig.xgrid.grid_line_color = 'navy'
fig.xgrid.grid_line_alpha = 0.6
fig.x_range = Range1d(.1, 22.4)
fig.y_range = Range1d(-0.1, 102)
show(fig)
export_png(fig, filename='../Images/l5_f.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_f.png'
y = sin(2pi100x) from x = 0 to 0.1 seconds, using 100 points and only 10 points
x1 = np.linspace(0, .1, 100)
x2 = np.linspace(0, .1, 10)
x3 = np.linspace(0, .1, 20)
x4 = np.linspace(0, .1, 19)
y1 = np.sin(2*np.pi*100*x1)
y2 = np.sin(2*np.pi*100*x2)
y3 = np.sin(2*np.pi*100*x3)
y4 = np.sin(2*np.pi*100*x4)
fig = figure(height=400, width=600)
fig.line(x1, y1, legend_label='100', line_width=3, alpha=.7)
fig.line(x3, y3, legend_label='20', color='green', line_width=3, alpha=.7)
fig.line(x4, y4, legend_label='19', color='purple', line_width=3, alpha=.7)
fig.line(x2, y2, legend_label='10', color='firebrick', line_width=3, alpha=.7)
fig.legend.orientation = 'horizontal'
fig.legend.title = 'N Samples'
fig.legend.title_text_font_size = '18pt'
fig.y_range = Range1d(-1.05, 2)
fig.yaxis.ticker=[-1,0,1]
style(fig, 'Time (s)', 'y(t)')
show(fig)
export_png(fig, filename='../Images/l5_optional.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_optional.png'
fft1, freqs1 = nu.fft(y1, x1)
fft2, freqs2 = nu.fft(y2, x2)
fig = figure()
fig.line(freqs1, fft1, legend_label = 'signal1')
fig.line(freqs2, fft2, legend_label = 'signal2', color = 'firebrick')
show(fig)
import librosa
from IPython.display import Image
Image('../Images/l5_optional_flute.jpg')
flute, sample_rate = librosa.load('./Data/cardboard_flute.mp3')
/home/trevormjs/anaconda3/envs/conda_env/lib/python3.8/site-packages/librosa/core/audio.py:165: UserWarning: PySoundFile failed. Trying audioread instead.
flute = pd.DataFrame({'ts': np.arange(0, len(flute))/sample_rate,
'mV': flute})
flute.shape
(41472, 2)
import librosa
from IPython.display import Image
Image('../Images/l5_optional_flute.jpg')
flute, sample_rate = librosa.load('./Data/cardboard_flute.mp3')
/home/trevormjs/anaconda3/envs/conda_env/lib/python3.8/site-packages/librosa/core/audio.py:165: UserWarning: PySoundFile failed. Trying audioread instead.
flute = pd.DataFrame({'ts': np.arange(0, len(flute))/sample_rate,
'mV': flute})
flute.shape
(41472, 2)
fig = figure()
fig.line(flute.ts, flute.mV)
show(fig)
flute_fft, flute_freqs = nu.fft(flute.mV[1000:3048], flute.ts, 15)
flute_harmonics, _ = get_peaks_etc(
flute_fft, flute_freqs, True)
# display(flute_harmonics)
flute_harmonics = flute_harmonics.loc[
(flute_harmonics.frequency > 200) &
(flute_harmonics.mV > 6)
]
fig = figure()
fig.line(flute_freqs/1000, flute_fft, legend_label='FFT')
fig.scatter(flute_harmonics.frequency/1000, flute_harmonics.mV,
color='firebrick', legend_label='Harmonics')
fig.x_range = Range1d(0, max(flute_freqs)/1000)
style(fig, 'Frequency (kHz)', 'Amplitude')
show(fig)
labels = {int(N): f'{note[0]} {note[1]}' for N, note in zip(
flute_harmonics.N, flute_harmonics.note)}
fig = figure(width=800, height=500)
fig.scatter(flute_harmonics.N, (flute_harmonics.A),
legend_label='flute?', size=10)
style(fig, 'N Harmonic', 'Scaled Amplitude')
ax2 = LinearAxis(axis_label='Note',)
ax2.ticker = list(labels.keys())
ax2.major_label_overrides = labels
ax2.major_label_orientation = np.pi/4
ax2.major_label_text_font_size = '14pt'
ax2.axis_label_text_font_size = '20pt'
# ax2.major_label_orientation = "vertical"
fig.add_layout(ax2, 'above')
fig.xgrid.visible = True
fig.xgrid.minor_grid_line_color = 'navy'
fig.xgrid.minor_grid_line_alpha = 0.6
fig.xgrid.grid_line_color = 'navy'
fig.xgrid.grid_line_alpha = 0.6
show(fig)
fig = figure()
fig.line(flute.ts, flute.mV)
show(fig)
flute_fft, flute_freqs = nu.fft(flute.mV[1000:3048], flute.ts, 15)
flute_harmonics, _ = get_peaks_etc(
flute_fft, flute_freqs, True)
# display(flute_harmonics)
flute_harmonics = flute_harmonics.loc[
(flute_harmonics.frequency > 200) &
(flute_harmonics.mV > 6)
]
fig = figure(width=600, height=400)
fig.line(flute_freqs/1000, flute_fft, legend_label='FFT')
fig.scatter(flute_harmonics.frequency/1000, flute_harmonics.mV,
color='firebrick', legend_label='Harmonics')
fig.x_range = Range1d(0, max(flute_freqs)/1000)
style(fig, 'Frequency (kHz)', 'Amplitude')
show(fig)
export_png(fig, filename='../Images/l5_optional_flute_fourier.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_optional_flute_fourier.png'
labels = {int(N): f'{note[0]} {note[1]}' for N, note in zip(
flute_harmonics.N, flute_harmonics.note)}
fig = figure(width=800, height=500)
fig.scatter(flute_harmonics.N, (flute_harmonics.A),
legend_label='flute?', size=10)
style(fig, 'N Harmonic', 'Scaled Amplitude')
ax2 = LinearAxis(axis_label='Note',)
ax2.ticker = list(labels.keys())
ax2.major_label_overrides = labels
ax2.major_label_orientation = np.pi/4
ax2.major_label_text_font_size = '14pt'
ax2.axis_label_text_font_size = '20pt'
# ax2.major_label_orientation = "vertical"
fig.add_layout(ax2, 'above')
fig.xgrid.visible = True
fig.xgrid.minor_grid_line_color = 'navy'
fig.xgrid.minor_grid_line_alpha = 0.6
fig.xgrid.grid_line_color = 'navy'
fig.xgrid.grid_line_alpha = 0.6
fig.xgrid.ticker = list(range(11))
fig.xaxis.ticker = list(range(11))
show(fig)
export_png(fig, filename='../Images/l5_optional_flute_harmonics.png')
'/home/trevormjs/Documents/Science/APL/Lab/Images/l5_optional_flute_harmonics.png'